home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / DIRUTIL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-14  |  20.3 KB  |  940 lines

  1. /* dirutil.c - MS-DOS directory reading routines
  2.  *
  3.  * Bdale Garbee, N3EUA, Dave Trulli, NN2Z, and Phil Karn, KA9Q
  4.  * Directory sorting by Mike Chepponis, K3MC
  5.  * New version using regs.h by Russell Nelson.
  6.  * Rewritten for Turbo-C 2.0 routines by Phil Karn, KA9Q 25 March 89
  7.  *
  8.  * Added path filter functions and applied to dodir
  9.  * also used by ftpcli.c, added current directory
  10.  * storage capability (11/92 WA3DSP)
  11.  * Bugfixes in the above by WG7J
  12.  */
  13.  
  14. #include "global.h"
  15. #include "ctype.h"
  16. #include "commands.h"
  17. #include "hardware.h"
  18. #include <sys/stat.h>
  19.  
  20. #ifndef UNIX
  21. # ifndef S_ISDIR
  22. #  define S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)
  23. # endif
  24. #else
  25. # ifdef HAVE_SYS_STATFS_H
  26. #  include <sys/statfs.h>
  27. #  define f_bavail f_bfree
  28. # else
  29. #  if defined(HAVE_SYS_PARAM_H) && !defined(_lint)
  30. #   include <sys/param.h>
  31. #  endif
  32. #  if defined(HAVE_SYS_MOUNT_H) && !defined(_lint)
  33. #   include <sys/mount.h>
  34. #  endif
  35. #  ifdef HAVE_SYS_VFS_H
  36. #   include <sys/vfs.h>
  37. #  endif
  38. # endif
  39. #endif    /* UNIX */
  40.  
  41. #ifndef _lint
  42. #include <time.h>
  43. #endif
  44. #if !defined (_lint) || !defined(MSDOS)
  45. #include "proc.h"
  46. #include "session.h"
  47. #endif
  48. #include "smtp.h"
  49.  
  50. #if !defined(_lint)
  51. static char rcsid[] OPTIONAL = "$Id: dirutil.c,v 1.33 1997/09/14 14:37:46 root Exp root $";
  52. #endif
  53.  
  54.  
  55. #ifdef CALLSERVER
  56. #include <string.h>
  57. #include <alloc.h>
  58. extern char *CDROM;        /* buckbook.c: defines CDROM drive letter e.g. "s:"  */
  59. #endif
  60.  
  61.  
  62. struct dirsort {
  63.     struct dirsort *next;
  64.     struct ffblk de;
  65. };
  66.  
  67.  
  68. #define    NULLSORT (struct dirsort *)0
  69.  
  70. static int nextname (int command, const char *name, struct ffblk * sbuf);
  71. static int dircmd (int argc,char *argv[],void *p);
  72. static char const *wildcardize (char const *path);
  73. static void commas (char *dest);
  74. static int fncmp (char *a, char *b);
  75. static void format_fname_full (FILE * file, struct ffblk * sbuf, int full, int n, const char *path);
  76. static void free_clist (struct dirsort * this);
  77. static void print_free_space (const char *path, FILE * file, int n);
  78. char *defpath (struct cur_dirs * curdirs, char *path);
  79. extern void crunch (char *buf, const char *path);
  80.  
  81. #ifdef TNOS_68K
  82. #define REGFILE    (FA_DIREC)
  83. #define ALLFILES "*"
  84. #include <modes.h>
  85. #else
  86. #define REGFILE    (FA_HIDDEN|FA_SYSTEM|FA_DIREC)
  87. #ifdef UNIX
  88. #define ALLFILES "*"
  89. #else
  90. #define ALLFILES "*.*"
  91. #endif
  92. #endif
  93.  
  94. #define    insert_ptr(list,new)    (new->next = list,list = new)
  95.  
  96.  
  97.  
  98. /* Create a directory listing in a temp file and return the resulting file
  99.  * descriptor. If full == 1, give a full listing; else return just a list
  100.  * of names.
  101.  */
  102. FILE *
  103. dir (char *path, int full)
  104. {
  105. FILE *fp;
  106. char *path1;
  107. char *path2;
  108.  
  109.     if ((fp = tmpfile ()) != NULLFILE) {
  110.         path1 = strdup ((!path) ? Command->curdirs->dir : path);
  111.         if (full == 1)
  112.             fprintf (fp, "Directory of %s at %s\n\n", path1, Hostname);
  113.         path2 = strdup (make_dir_path (2, path1, Command->curdirs->dir));
  114.         (void) getdir (path2, full, fp);
  115.         free (path1);
  116.         free (path2);
  117.         rewind (fp);
  118.     }
  119.     return fp;
  120. }
  121.  
  122.  
  123.  
  124. /* find the first or next file and lowercase it. */
  125. static int
  126. nextname (int command, const char *name, struct ffblk *sbuf)
  127. {
  128. int found;
  129.  
  130.     switch (command) {
  131.         case 0:
  132.             found = findfirst (name, sbuf, REGFILE);
  133.             break;
  134.         default:
  135.             found = findnext (sbuf);
  136.     }
  137.     found = (found == 0);
  138. #ifndef UNIX
  139.     if (found)
  140.         (void) strlwr (sbuf->ff_name);
  141. #endif
  142.  
  143.     return found;
  144. }
  145.  
  146.  
  147.  
  148. /* wildcard filename lookup */
  149. int
  150. filedir (const char *name, int times, char *ret_str)
  151. {
  152. static struct ffblk sbuf;
  153. int rval;
  154.  
  155.     switch (times) {
  156.         case 0:
  157.             rval = findfirst (name, &sbuf, REGFILE);
  158.             break;
  159.         default:
  160.             rval = findnext (&sbuf);
  161.             break;
  162.     }
  163.     if (rval != 0)
  164.         ret_str[0] = '\0';
  165.     else            /* Copy result to output */
  166.         strcpy (ret_str, sbuf.ff_name);
  167.     return rval;
  168. }
  169.  
  170.  
  171.  
  172. /* do a directory list to the stream
  173.  * full = 0 -> short form, 1 is long, 2 is long with "|" down center, and
  174.  * -1 is short with two entries per line.
  175. */
  176. int
  177. getdir (char const *path, int full, FILE *file)
  178. {
  179. struct ffblk sbuf;
  180. int command = 0;
  181. int n = 0;
  182. struct dirsort *head, *here, *new;
  183.  
  184.     path = wildcardize (path);
  185.     head = NULLSORT;    /* No head of chain yet... */
  186.     for (;;) {
  187.         kwait (NULL);
  188.         if (!nextname (command, path, &sbuf))
  189.             break;
  190.         command = 1;    /* Got first one already... */
  191. #ifdef MSDOS
  192.         if (sbuf.ff_name[0] == '.')    /* drop "." and ".." */
  193.             continue;
  194. #endif
  195.  
  196.         new = (struct dirsort *) mallocw (sizeof (struct dirsort));
  197.  
  198.         new->de = sbuf;    /* Copy contents of directory entry struct */
  199.  
  200.         /* insert it into the list */
  201.         if (!head || fncmp (new->de.ff_name, head->de.ff_name) < 0)
  202.             insert_ptr (head, new);
  203.         else {
  204.             register struct dirsort *this;
  205.  
  206.             for (this = head; this->next != NULLSORT; this = this->next)
  207.                 if (fncmp (new->de.ff_name, this->next->de.ff_name) < 0)
  208.                     break;
  209.             insert_ptr (this->next, new);
  210.         }
  211.     }            /* infinite FOR loop */
  212.  
  213.     for (here = head; here; here = here->next)
  214.         format_fname_full (file, &here->de, full, ++n, path);
  215.  
  216.     /* Give back all the memory we temporarily needed... */
  217.     free_clist (head);
  218.  
  219.     if (full == 1)
  220.         print_free_space (path, file, n);
  221.  
  222.     if ((full == -1) && (n & 1))
  223.         fputs ("\n", file);
  224.  
  225.     return 0;
  226. }
  227.  
  228.  
  229.  
  230. static int
  231. fncmp (register char *a, register char *b)
  232. {
  233. int i;
  234.  
  235.     for (;;) {
  236. #ifdef MSDOS
  237.         if (*a == '.')
  238.             return -1;
  239.         if (*b == '.')
  240.             return 1;
  241. #endif
  242.         if ((i = *a - *b++) != 0)
  243.             return i;
  244.         if (!*a++)
  245.             return -1;
  246.     }
  247. }
  248.  
  249.  
  250.  
  251. #ifdef ALLCMD
  252. /* Change working directory */
  253. int
  254. docd (int argc, char *argv[], void *p OPTIONAL)
  255. {
  256.     if (argc > 1) {
  257.         if (!dir_ok (argv[1], Command->curdirs)) {
  258.             tprintf ("Invalid Drive/Directory - %s\n", argv[1]);
  259.             return 1;
  260.         }
  261.     }
  262.     tprintf ("Local Directory - %s\n", Command->curdirs->dir);
  263.     return 0;
  264. }
  265.  
  266.  
  267.  
  268. #ifdef MSDOS
  269. /* Change working drive */
  270. int
  271. dodrive (int argc, char *argv[], void *p)
  272. {
  273. char **margv;
  274.  
  275.     margv = (char **) callocw (2, sizeof (char *));
  276.  
  277.     margv[1] = strdup (argv[0]);
  278.     (void) docd (2, margv, p);
  279.     free (margv[1]);
  280.     free (margv);
  281.     return 0;
  282. }
  283.  
  284. #endif /* MSDOS*/
  285. #endif /* ALLCMD */
  286.  
  287.  
  288.  
  289. char *
  290. defpath (struct cur_dirs *curdirs OPTIONAL, char *path)
  291. {
  292. #ifdef MSDOS
  293. int drive;
  294.  
  295.     drive = tolower (path[0]) - '`';
  296.     if (strlen (path) == 2 && path[1] == ':' && curdirs->curdir[drive] != NULLCHAR)
  297.         return curdirs->curdir[drive];
  298.     else
  299. #endif
  300.         return path;
  301. }
  302.  
  303.  
  304.  
  305. #if (defined(ALLCMD) || defined(ALLSESSIONS))
  306. /* List directory to console */
  307. static int
  308. dircmd (int argc, char *argv[], void *p)
  309. {
  310. char *path, *file;
  311. FILE *fp;
  312. char tmpname[80];
  313. char **margv;
  314.  
  315.     if (argc > 1) {
  316.         file = strdup (make_fname (Command->curdirs->dir, defpath (Command->curdirs, argv[1])));
  317.         path = strdup (make_dir_path (argc, file, Command->curdirs->dir));
  318.         free (file);
  319.     } else
  320.         path = strdup (Command->curdirs->dir);
  321.     margv = (char **) callocw (2, sizeof (char *));
  322.  
  323.     (void) tmpnam (tmpname);
  324.     fp = fopen (tmpname, WRITE_TEXT);
  325.     if (fp) {
  326.         (void) getdir (path, 1, fp);
  327.         free (path);
  328.         (void) fclose (fp);
  329.     }
  330.     margv[1] = strdup (tmpname);
  331.     (void) morecmd (2, margv, p);
  332.     free (margv[1]);
  333.     free (margv);
  334.     unlink (tmpname);
  335.     return 0;
  336. }
  337.  
  338.  
  339.  
  340. int
  341. dodir (int argc, char *argv[], void *p)
  342. {
  343. char **pargv;
  344. int i;
  345.  
  346.     if (Curproc->input == Command->input) {
  347.         /* Make private copy of argv and args,
  348.          * spawn off subprocess and return.
  349.          */
  350.         pargv = (char **) callocw ((unsigned) argc + 1, sizeof (char *));
  351.  
  352.         for (i = 0; i < argc; i++)
  353.             pargv[i] = strdup (argv[i]);
  354.         pargv[i] = NULL;
  355.         (void) newproc ("dir", 512, (void (*)(int, void *, void *)) dircmd, argc, (void *) pargv, p, 1);
  356.     } else
  357.         (void) dircmd (argc, argv, p);
  358.     return 0;
  359. }
  360.  
  361. #endif /* ALLCMD || ALLSESSIONS */
  362.  
  363.  
  364.  
  365. #ifdef ALLCMD
  366. /* Create directory */
  367. int
  368. domkd (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
  369. {
  370. char path[128];
  371.  
  372.     strncpy (path, make_fname (Command->curdirs->dir, argv[1]), 128);
  373.  
  374.     if (mkdir (path, 0777) == -1)
  375.         tprintf ("Can't make %s: %s\n", path, SYS_ERRLIST(errno));
  376.     return 0;
  377. }
  378.  
  379.  
  380.  
  381. /* Remove directory */
  382. int
  383. dormd (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
  384. {
  385. char path[128];
  386.  
  387.     strncpy (path, make_fname (Command->curdirs->dir, argv[1]), 128);
  388.     if (rmdir (path) == -1)
  389.         tprintf ("Can't remove %s: %s\n", path, SYS_ERRLIST(errno));
  390.     return 0;
  391. }
  392.  
  393. #endif /*ALLCMD*/
  394.  
  395.  
  396.  
  397. /*
  398.  * Return a string with commas every 3 positions.
  399.  * the original string is replace with the string with commas.
  400.  *
  401.  * The caller must be sure that there is enough room for the resultant
  402.  * string.
  403.  *
  404.  *
  405.  * k3mc 4 Dec 87
  406.  */
  407. static void
  408. commas (char *dest)
  409. {
  410. char *src, *core;    /* Place holder for malloc */
  411. unsigned cc;        /* The comma counter */
  412. unsigned len;
  413.  
  414.     if (!dest)
  415.         return;
  416.     len = strlen (dest);
  417.     /* Make a copy, so we can muck around */
  418.     core = src = strdup (dest);
  419.  
  420.     cc = (len - 1) % 3 + 1;    /* Tells us when to insert a comma */
  421.  
  422.     while (*src != '\0') {
  423.         *dest++ = *src++;
  424.         if (((--cc) == 0) && *src) {
  425.             *dest++ = ',';
  426.             cc = 3;
  427.         }
  428.     }
  429.     free (core);
  430.     *dest = '\0';
  431. }
  432.  
  433.  
  434.  
  435. /* fix up the filename so that it contains the proper wildcard set */
  436. static char const *
  437. wildcardize (char const *path)
  438. {
  439. #ifndef TNOS_68K
  440. #define THISSIZE 64
  441. #else
  442. #ifdef UNIX
  443. #define THISSIZE 1024
  444. #else
  445. #define THISSIZE 128
  446. #endif
  447. #endif
  448. struct ffblk sbuf;
  449. static char ourpath[THISSIZE];
  450.  
  451.     /* Root directory is a special case */
  452.     if (path == NULLCHAR || *path == '\0' ||
  453.         strcmp (path, "\\") == 0 || strcmp (path, "/") == 0) {
  454. #ifdef MSDOS
  455.         path = "\\*.*";
  456. #else
  457.         path = "/*";
  458. #endif
  459.         return path;
  460.     }
  461. #ifdef MSDOS
  462.     /* MSDOS Root directory can also have a drive letter prefix */
  463.     if (isalpha (*path) &&
  464.       (strcmp (path + 1, ":\\") == 0 || strcmp (path + 1, ":/") == 0)) {
  465.         sprintf (ourpath, "%c:/*.*", *path);
  466.         return ourpath;
  467.     }
  468. #endif
  469.  
  470. #ifdef CALLSERVER
  471.     if (CDROM != NULLCHAR && strcmp (path, CDROM) == 0) {
  472.         path = (char *) mallocw (7);    /* THIS causes a memory leak ! - WG7J */
  473.         sprintf (path, "%s/*.*", CDROM);
  474.     }
  475. #endif
  476.  
  477.     /* if they gave the name of a subdirectory, append \*.* to it */
  478.     if (
  479. #ifdef TNOS_68K
  480.            (*path == '/' && !(strchr (path + 1, '/'))) ||
  481. #endif
  482.            (nextname (0, path, &sbuf) &&
  483.             (sbuf.ff_attrib & FA_DIREC) &&
  484.             !nextname (1, path, &sbuf))) {
  485.  
  486.         /* if there isn't enough room, give up -- it's invalid anyway */
  487.         if (strlen (path) + 4 > (THISSIZE - 1))
  488.             return path;
  489.         strncpy (ourpath, path, THISSIZE - 4);
  490. #ifndef MSDOS
  491.         strcat (ourpath, "/*");
  492. #else
  493.         strcat (ourpath, "\\*.*");
  494. #endif
  495.         return ourpath;
  496.     }
  497.     return path;
  498. }
  499.  
  500.  
  501. #if defined(TNOS_68K) || defined(UNIX)
  502.  
  503. static void
  504. format_fname_full (FILE *file, struct ffblk *sbuf, int full, int n, const char *path)
  505. {
  506. static char line_buf[1025];
  507. static char cbuf[1025];
  508. struct stat sb;
  509. char *symlinkpath = NULLCHAR;
  510. char *tcbuf;
  511.  
  512.     strncpy (cbuf, sbuf->ff_name, sizeof (sbuf->ff_name));
  513.     if (sbuf->ff_attrib & FA_DIREC)
  514.         strcat (cbuf, "/");
  515.     if (full == 1) {
  516.         /* Long form, give other info too */
  517.         sprintf (line_buf, "%-14s", cbuf);
  518.         if (strlen (cbuf) > 14)
  519.             strcpy (&line_buf[12], "..");
  520.         if (sbuf->ff_attrib & FA_DIREC)
  521.             strcat (line_buf, "          ");    /* 10 spaces */
  522.         else {
  523.             sprintf (cbuf, "%ld", sbuf->ff_fsize);
  524.             commas (cbuf);
  525.             sprintf (line_buf + strlen (line_buf), "%9s ", cbuf);
  526.         }
  527.         sprintf (line_buf + strlen (line_buf), "%2d:%02d %2d/%02d/%02d%s",
  528.              sbuf->ff_ftime.tm_hour, sbuf->ff_ftime.tm_min,
  529.              sbuf->ff_ftime.tm_mon + 1, sbuf->ff_ftime.tm_mday,
  530.              sbuf->ff_ftime.tm_year,
  531.              (full == 2) ? " | \n" : (n & 1) ? "   " : "\n");
  532.         fputs (line_buf, file);
  533.     } else if (full == 2) {
  534.         if (sbuf->ff_attrib & FA_DIREC)
  535.             cbuf[strlen (cbuf) - 1] = 0;    /* strip off the '/' */
  536.  
  537.         tcbuf = mallocw (strlen(cbuf) + strlen(path) + 2);
  538.         strcpy (tcbuf, path);
  539.         if (tcbuf[strlen(tcbuf) - 1] == '*')
  540.             tcbuf[strlen(tcbuf) - 1] = 0;
  541.         strcat (tcbuf, cbuf);
  542.         (void) lstat (tcbuf, &sb);
  543.         if (S_ISLNK(sb.st_mode))    {
  544.             symlinkpath = callocw (1024, 1);
  545.             if (readlink (tcbuf, symlinkpath, 1024) < 0)    {
  546.                 free (symlinkpath);
  547.                 symlinkpath = NULLCHAR;
  548.             }
  549.         }
  550.  
  551.         sprintf (line_buf, "%c%c%c%c%c%c%c%c%c%c   1 tnos     tnos     %8ld %3.3s %2d %2d:%02d %s%s%s\n",
  552.              (S_ISDIR (sb.st_mode)) ? 'd' : (S_ISLNK (sb.st_mode)) ? 'l' : '-',
  553.              (sb.st_mode & S_IRUSR) ? 'r' : '-',
  554.              (sb.st_mode & S_IWUSR) ? 'w' : '-',
  555.              (sb.st_mode & S_IXUSR) ? 'x' : '-',
  556.              (sb.st_mode & S_IRGRP) ? 'r' : '-',
  557.              (sb.st_mode & S_IWGRP) ? 'w' : '-',
  558.              (sb.st_mode & S_IXGRP) ? 'x' : '-',
  559.              (sb.st_mode & S_IROTH) ? 'r' : '-',
  560.              (sb.st_mode & S_IWOTH) ? 'w' : '-',
  561.              (sb.st_mode & S_IXOTH) ? 'x' : '-',
  562.              sbuf->ff_fsize,
  563.              Months[sbuf->ff_ftime.tm_mon],
  564.              sbuf->ff_ftime.tm_mday,
  565.              sbuf->ff_ftime.tm_hour, sbuf->ff_ftime.tm_min,
  566.              cbuf,
  567.              (symlinkpath != NULLCHAR) ? " -> " : "",
  568.              (symlinkpath != NULLCHAR) ? symlinkpath : "");
  569.         fputs (line_buf, file);
  570.     } else {
  571.         if (!full) {
  572.             fputs (cbuf, file);
  573.             fputs ("\n", file);
  574.         } else {
  575.             fprintf (file, "%-37.37s", cbuf);
  576.             fputs ((n & 1) ? "   " : "\n", file);
  577.         }
  578.     }
  579. }
  580.  
  581.  
  582. #else        /* MSDOS */
  583.  
  584.  
  585. static void
  586. format_fname_full (FILE *file, struct ffblk *sbuf, int full, int n, const char *path)
  587. {
  588. char line_buf[80];    /* for long dirlist */
  589. char cbuf[20];        /* for making line_buf */
  590. char which;
  591.  
  592.     strncpy (cbuf, sbuf->ff_name, 20);
  593.     if (sbuf->ff_attrib & FA_DIREC)
  594.         strcat (cbuf, "/");
  595.     if (full == 1) {
  596.         /* Long form, give other info too */
  597.         sprintf (line_buf, "%-13s", cbuf);
  598.         if (sbuf->ff_attrib & FA_DIREC)
  599.             strcat (line_buf, "           ");    /* 11 spaces */
  600.         else {
  601.             sprintf (cbuf, "%ld", sbuf->ff_fsize);
  602.             commas (cbuf);
  603.             sprintf (line_buf + strlen (line_buf), "%10s ", cbuf);
  604.         }
  605.         sprintf (line_buf + strlen (line_buf), "%2d:%02d %2d/%02d/%02d%s",
  606.              (sbuf->ff_ftime >> 11) & 0x1f,    /* hour */
  607.              (sbuf->ff_ftime >> 5) & 0x3f,    /* minute */
  608.              (sbuf->ff_fdate >> 5) & 0xf,    /* month */
  609.              (sbuf->ff_fdate) & 0x1f,    /* day */
  610.              (sbuf->ff_fdate >> 9) + 80,    /* year */
  611.              (full == 2) ? " | \n" : (n & 1) ? "   " : "\n");
  612.         fputs (line_buf, file);
  613.     } else if (full == 2) {
  614.         if (sbuf->ff_attrib & FA_DIREC)
  615.             cbuf[strlen (cbuf) - 1] = 0;    /* strip off the '/' */
  616.         which = (sbuf->ff_attrib & FA_RDONLY) ? '-' : 'w';
  617.         sprintf (line_buf, "%cr%c-r%c-r%c-   1 tnos     tnos     %8ld %3.3s %2d %2d:%02d %s\n",
  618.              (sbuf->ff_attrib & FA_DIREC) ? 'd' : '-', which, which, which,
  619.              sbuf->ff_fsize,
  620.              Months[(sbuf->ff_fdate >> 5) & 0xf],
  621.              (sbuf->ff_fdate) & 0x1f,    /* day */
  622.              (sbuf->ff_ftime >> 11) & 0x1f,    /* hour */
  623.              (sbuf->ff_ftime >> 5) & 0x3f,    /* minute */
  624.              cbuf);
  625.         fputs (line_buf, file);
  626.     } else {
  627.         if (!full) {
  628.             fputs (cbuf, file);
  629.             fputs ("\n", file);
  630.         } else {
  631.             fprintf (file, "%-37.37s", cbuf);
  632.             fputs ((n & 1) ? "   " : "\n", file);
  633.         }
  634.     }
  635. }
  636. #endif
  637.  
  638.  
  639.  
  640. /* Provide additional information only on DIR */
  641. static void
  642. print_free_space (const char *path, FILE *file, int n)
  643. {
  644. unsigned long free_bytes, total_bytes;
  645. char s_free[20], s_total[20];
  646. char cbuf[20];
  647. #ifdef UNIX
  648. char *pbuf;
  649. struct statfs vfsb;
  650. char *cp;
  651.  
  652.     pbuf = mallocw (1024);
  653.     strncpy (pbuf, path, 1024 - 2);
  654.     if ((cp = strrchr (pbuf, '/')) == 0)
  655.         strcat (pbuf, "/.");
  656.     else {
  657.         *++cp = '.';
  658.         *++cp = '\0';
  659.     }
  660. #if defined(HAVE_SYS_STATFS_H) && !defined(linux)
  661.     statfs (pbuf, &vfsb, sizeof vfsb, 0);
  662. #else
  663.     (void) statfs (pbuf, &vfsb);
  664. #endif
  665.     free_bytes = (unsigned long) (vfsb.f_bsize * vfsb.f_bavail);
  666.     total_bytes = (unsigned long) (vfsb.f_bsize * vfsb.f_blocks);
  667. #else    /* MSDOS or TNOS_68K */
  668. struct dfree dtable;
  669. unsigned long bpcl;
  670.  
  671. #ifdef MSDOS
  672. int drive;
  673.  
  674.     if (path[1] == ':')
  675.         drive = toupper(path[0]) - '@';
  676.     else
  677.         drive = 0;
  678. #endif
  679.     /* Find disk free space */
  680. #ifndef TNOS_68K
  681.     getdfree (uchar(drive), &dtable);
  682. #else
  683.     getdfree (path, &dtable);
  684. #endif
  685.  
  686.     bpcl = dtable.df_bsec * dtable.df_sclus;
  687.     free_bytes = dtable.df_avail * bpcl;
  688.     total_bytes = dtable.df_total * bpcl;
  689. #endif
  690.  
  691.     if (n & 1)
  692.         fputs ("\n", file);
  693.  
  694.     sprintf (s_free, "%ld", free_bytes);
  695.     commas (s_free);
  696.     sprintf (s_total, "%ld", total_bytes);
  697.     commas (s_total);
  698.  
  699.     if (n)
  700.         sprintf (cbuf, "%d", n);
  701.     else
  702.         strcpy (cbuf, "No");
  703.  
  704.     fprintf (file, "%s file%s. %s bytes free. Disk size %s bytes.\n",
  705.          cbuf, (n == 1 ? "" : "s"), s_free, s_total);
  706. }
  707.  
  708.  
  709.  
  710. static void
  711. free_clist (struct dirsort *this)
  712. {
  713. struct dirsort *next;
  714.  
  715.     while (this != NULLSORT) {
  716.         next = this->next;
  717.         free (this);
  718.         this = next;
  719.     }
  720. }
  721.  
  722.  
  723.  
  724. /* Translate those %$#@!! backslashes to proper form */
  725. void
  726. undosify (char *s)
  727. {
  728.     if (s) {
  729.         while (*s != '\0') {
  730.             if (*s == '\\')
  731.                 *s = '/';
  732.             s++;
  733.         }
  734.     }
  735. }
  736.  
  737.  
  738.  
  739. char *
  740. make_dir_path (int count, char *arg, const char *curdir)
  741. {
  742. char *tmpdir, *retval;
  743. char path[1024], *q;
  744.  
  745.     undosify (arg);
  746.     tmpdir = strdup (curdir);
  747.     undosify (tmpdir);
  748.     if (count >= 2) {
  749.         q = arg;
  750.         q += strlen (arg) - 1;
  751. #ifndef TNOS_68K
  752.         if (*q == '/' || *q == ':')
  753. #else
  754.         if (*q == '/')
  755. #endif
  756.         {
  757.             strncpy (path, arg, 1024 - strlen (ALLFILES));
  758.             strcat (path, ALLFILES);
  759.         } else
  760.             strncpy (path, arg, 1024);
  761.     } else
  762.         strncpy (path, ALLFILES, 1024);
  763.  
  764.     retval = make_fname (tmpdir, path);
  765.     free (tmpdir);
  766.     return (retval);
  767. }
  768.  
  769.  
  770.  
  771. char *
  772. make_fname (const char *curdir, const char *fname0)
  773. {
  774. char *p, *fname;
  775. static char new_name[1024];
  776.  
  777.     strncpy (new_name, curdir, 1024);
  778.     fname = strdup (fname0);
  779.     if (fname)
  780.         undosify (fname);
  781.     if (fname && *fname) {
  782.         if (*fname == '.') {
  783.             if (*++fname == '/')
  784.                 fname++;
  785.             else if (*fname == '.') {
  786.                 p = strrchr (new_name, '/');
  787.                 if (p)
  788.                     *p = 0;
  789.                 if (*++fname == '/')
  790.                     fname++;
  791.             }
  792.         }
  793. #ifdef MSDOS
  794.         if (fname[0] == '/' || (strchr (fname, ':') != NULLCHAR))
  795. #else
  796.         if (fname[0] == '/')
  797. #endif
  798.             return fname;
  799.         else {
  800.             p = new_name;
  801.             p += strlen (p) - 1;
  802.             if (*p == '/')
  803.                 *p = '\0';
  804.             crunch (new_name, fname);
  805. #ifdef MSDOS
  806.             if (new_name[strlen (new_name) - 1] == ':')
  807.                 strcat (new_name, "/");
  808. #endif
  809.         }
  810.     }
  811.     return new_name;
  812. }
  813.  
  814.  
  815.  
  816. /* Check Drive/Directory for validity - 1=OK, 0=NOGOOD */
  817. int
  818. dir_ok (char *newpath, struct cur_dirs *dirs)
  819. {
  820. int result;
  821. char fullpath[1024];
  822. #ifdef TNOS_68K
  823. int new = 0;
  824.  
  825.     undosify (newpath);
  826.     strlwr (newpath);
  827.     result = ((access (newpath, S_IFDIR) == -1) ? 0 : 1);
  828.     if (result) {
  829.         /*        chdir (newpath);    */
  830.         new = (*newpath == '/');
  831.         sprintf (fullpath, "%s%s%s", !new ? dirs->dir : "", !new ? "/" : "", newpath);
  832.         free (dirs->dir);
  833.         dirs->dir = strdup (fullpath);
  834.     }
  835.     return (result);
  836. #else    /* either MSDOS or UNIX */
  837. char curpath[1024];
  838. char buf[128];
  839.  
  840. #ifdef MSDOS
  841. int drive = dirs->drv;
  842. #endif
  843. struct stat sbuf;
  844.  
  845.  
  846.     undosify (newpath);
  847.     strncpy (buf, newpath, 128);
  848.     strncpy (curpath, dirs->dir, 1024);
  849.  
  850. #ifdef MSDOS
  851.     if (buf[1] == ':')    {
  852.         strncpy (fullpath, buf, 1024);
  853.     } else
  854. #endif
  855.     {
  856.         if (*buf != '/')
  857.             crunch (curpath, buf);
  858.         else
  859.             strncpy (curpath, buf + 1, 1024);
  860.  
  861. #ifdef UNIX
  862.         sprintf (fullpath, "%s%s", (*curpath != '/' ? "/" : ""), curpath);
  863. #else
  864.         strncpy (fullpath, curpath, 1024);
  865. #endif
  866.     }
  867.  
  868.     if (stat (fullpath, &sbuf) == -1 || !S_ISDIR (sbuf.st_mode))
  869.         result = 0;
  870.     else if ((result = access (fullpath, 0) + 1) == 1) {
  871. #ifdef UNIX
  872.         free (dirs->dir);
  873.         dirs->dir = strdup (fullpath);
  874. #else
  875.         if (dirs->curdir[drive])
  876.             free (dirs->curdir[drive]);
  877.         dirs->curdir[drive] = strdup (fullpath);
  878.         dirs->drv = drive;
  879.         dirs->dir = dirs->curdir[drive];
  880. #endif
  881.     }
  882.     return result;
  883. #endif
  884. }
  885.  
  886.  
  887.  
  888. const char *
  889. init_dirs (struct cur_dirs *dirs)
  890. {
  891. #ifdef UNIX
  892.     dirs->dir = strdup (getcwd (NULL, 1024));
  893.     return dirs->dir;
  894. #endif
  895. #ifdef TNOS_68K
  896. char fullpath[1024];
  897.  
  898.     dirs->dir = strdup (getcwd (fullpath, 1024));
  899.     return (dirs->dir);
  900. #endif
  901. #ifdef MSDOS
  902. char buf[128], fullpath[128];
  903. int x, drive;
  904.  
  905.     for (x = 0; x <= 26; x++)
  906.         dirs->curdir[x] = 0;
  907.  
  908.     drive = getdisk () + 1;
  909.     (void) getcwd (buf, 128);
  910.     undosify (buf);
  911.     (void) strlwr (buf);
  912.     sprintf (fullpath, "%c:/%s", drive + '`', &buf[3]);
  913.     dirs->curdir[drive] = strdup (fullpath);
  914.     dirs->drv = drive;
  915.     dirs->dir = dirs->curdir[drive];
  916.     return dirs->curdir[drive];
  917. #endif
  918. }
  919.  
  920.  
  921.  
  922. void
  923. free_dirs (struct cur_dirs *dirs)
  924. {
  925. #ifdef UNIX
  926.     free (dirs->dir);
  927. #else
  928. #ifdef TNOS_68K
  929.     free (dirs->dir);
  930. #else
  931. int x;
  932.  
  933.     for (x = 0; x <= 26; x++) {
  934.         if (dirs->curdir[x])
  935.             free (dirs->curdir[x]);
  936.     }
  937. #endif
  938. #endif
  939. }
  940.